package com.zxg.zbc.web.common.module;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.citrus.service.requestcontext.parser.ParameterParser;
import com.alibaba.citrus.turbine.Context;
import com.alibaba.citrus.turbine.Navigator;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.taobao.api.internal.util.WebUtils;
import com.zxg.util.WeixinApiConfigs;
import com.zxg.util.WeixinComponent;
import com.zxg.zbc.domain.UUIIResult;
import com.zxg.zbc.web.common.config.SessionConfig;

public abstract class BaseWeixinModule {

  @Autowired
  protected HttpSession         session;

  @Autowired
  HttpServletRequest            request;

  static String                 MP_WEB_AUTH        = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";
  static String                 MP_WEB_ACCESSTOKEN = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code ";
  protected final static Logger log                = LoggerFactory.getLogger(BaseWeixinModule.class);

  public void execute(Context context, ParameterParser params, Navigator nav) {
    String ip = getClientIP(request);
    log.warn("ip:" + ip);

    String openId = checkPermisionAndRedi(params, nav, context);

    doExecute(context, params, nav, openId, ip);

  }

  private String getOpenIdFromSession() {
    if (session.getAttribute(SessionConfig.SESSION_WEIXIN) == null)
      return null;
    return (String) session.getAttribute(SessionConfig.SESSION_WEIXIN);
  }

  protected WeixinComponent generateCurrentApp() {
    return WeixinComponent.ZXG;
  }

  public abstract void doExecute(Context context, ParameterParser params, Navigator nav, String openId, String ip);

  protected String checkPermisionAndRedi(ParameterParser params, Navigator nav, Context context) {
    String code = params.getString("code");

    String rediUrl = request.getRequestURL().toString() + "?" + request.getQueryString();
    try {
      rediUrl = URLEncoder.encode(rediUrl, "utf8");
    } catch (UnsupportedEncodingException e1) {
      log.error("error", e1);
    }
    String scope = "snsapi_base";
    String openId = getOpenIdFromSession();
    if (openId != null)
      return openId;
    if (code == null) {
      String url = MP_WEB_AUTH.replaceAll("REDIRECT_URI", rediUrl).replaceAll("STATE", "zxg").replaceAll("SCOPE", scope).replaceAll("APPID",
          WeixinApiConfigs.getAppInfoByApp(WeixinComponent.getAPP("zxg")).getAppId());
      nav.redirectToLocation(url);
      return null;
    } else {
      return oAuthedPage(params, context, nav);
    }

  }

  public JSONObject getWebMpAuthFansAccesstoken(String appId, String code, WeixinComponent component) {
    try {
      String url = MP_WEB_ACCESSTOKEN.replaceAll("CODE", code).replaceAll("SECRET", WeixinApiConfigs.getAppInfoByApp(component).getAppSecret())
          .replaceAll("APPID", appId);

      String res = WebUtils.doGet(url, null);
      log.warn(res);
      if (res != null && !res.equals("")) {
        return JSON.parseObject(res);
      }
    } catch (IOException e) {
      log.error("error", e);
      return null;
    }

    return null;
  }
  private String oAuthedPage(ParameterParser params, Context context, Navigator nav) {

    String code = params.getString("code");
    String state = "zxg";

    if (state != null && code != null) {
      WeixinComponent com = WeixinComponent.getAPP(state);
      JSONObject accessToken = getWebMpAuthFansAccesstoken(WeixinApiConfigs.getAppInfoByApp(WeixinComponent.getAPP("zxg")).getAppId(), code, com);
      log.warn(accessToken.toJSONString());
      if (accessToken != null && accessToken.getString("openid") != null) {

        String openId = accessToken.getString("openid");
        session.setAttribute(SessionConfig.SESSION_WEIXIN, openId);
        return openId;
      }

    }
    return null;

  }

  protected void convertSuccessJson(Object o, Context context) {
    try {
      context.put("result", new UUIIResult(true, o, "success"));
    } catch (Error e) {
      log.error("errorrrrrrr", e);
      context.put("result", new UUIIResult(true, o, "success"));

    } catch (Exception ee) {
      log.error("err", ee);
      context.put("result", new UUIIResult(true, o, "success"));
    }
  }

  protected void convertSuccessJson(int code, String message, Context context) {
    context.put("result", new UUIIResult(true, code, message));
  }

  protected void convertJson(Object o, Context context) {
    context.put("result", o);
  }

  protected void convertFailureJson(String message, Context context) {
    context.put("result", new UUIIResult(false, null, message));
  }

  protected void convertFailureJson(int code, String message, Context context) {
    context.put("result", new UUIIResult(false, code, message));
  }

  protected boolean skipPermission() {
    return false;
  }

  /***
   * 获取客户端IP地址;这里通过了Nginx获取;X-Real-IP,
   * 
   * @param request
   * @return
   */
  public String getClientIP(HttpServletRequest request) {
    String fromSource = "X-Real-IP";
    String ip = request.getHeader("X-Real-IP");
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
      ip = request.getHeader("X-Forwarded-For");
      fromSource = "X-Forwarded-For";
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
      ip = request.getHeader("Proxy-Client-IP");
      fromSource = "Proxy-Client-IP";
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
      ip = request.getHeader("WL-Proxy-Client-IP");
      fromSource = "WL-Proxy-Client-IP";
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
      ip = request.getRemoteAddr();
      fromSource = "request.getRemoteAddr";
    }
    log.warn("App Client IP: " + ip + ", fromSource: " + fromSource);
    return ip;
  }

}
